package ge.lowlevel.js;

import ge.exceptions.FunctionNonSuported;
import ge.lowlevel.IOEngine;

/**
 * 
 * @author Abel
 * IOEngine implementation in JavaScript 
 */
public class JSIOEngine extends IOEngine 
{
	public JSIOEngine()
	{
		init();
	}
	
	private native void init()
	/*-{
		var timeLimit = 100;
		//Vectores de Eventos
		$wnd.keys = new Array();
		$wnd.keysDown = new Array();
		$wnd.keysUp = new Array();
		$wnd.buttonD = new Array();
		$wnd.buttonU = new Array();
		$wnd.mouseOut = new Array();
		$wnd.keysOut = new Array();
		$wnd.keysUpOut = new Array();
		$wnd.mouseX = 0;
		$wnd.mouseY = 0;
		
	 
		
		
		$wnd.addEventListener('keydown',keyDown,true);
		$wnd.addEventListener('keyup',keyUp,true);
		
		
		$wnd.addEventListener ("mousemove", MoveMouse, true);
  		function MoveMouse(evt)
  		{
  			 
		    $wnd.mouseX = evt.clientX;
		 	$wnd.mouseY = evt.clientY;
		 	//$wnd.alert("Mouse: X="+$wnd.mouseX+",Y="+$wnd.mouseY);
		}
		//Raton
		if ($wnd.addEventListener)
		{
		    $wnd.addEventListener("mousedown", mouseDown, true);
			$wnd.addEventListener("mouseup", mouseUp,true);
		}
		else
		{
		   $wnd.attachEvent("onmousedown", mouseDown);
		   $wnd.attachEvent("onmouseup", mouseUp);
		}
		  
		 
		 
		$wnd.clickEnd = function()
		{
			if($wnd.mouseOut.length > 0)
			{
				id = $wnd.mouseOut.shift();
				$wnd.buttonU[id] = false;
			}
		}
	 
		function keyDown(evt)
		{
			 
			$wnd.keysDown[evt.keyCode] = true;
			$wnd.keys[evt.keyCode] = true;
			$wnd.keysOut.push(evt.keyCode);
			setTimeout("$wnd.justPress()",timeLimit);
		}
		 
		$wnd.justPress = function()
		{
					 
			if($wnd.keysOut.length > 0)
			{
				
				key = $wnd.keysOut.shift();
				$wnd.keysDown[key] = false;
				//$wnd.alert(key +" time out");
			}
		}
		 
		function keyUp(evt)
		{
		 
			$wnd.keys[evt.keyCode] = false;
			$wnd.keysUp[evt.keyCode] = true;
			$wnd.keysUpOut.push(evt.keyCode)
			 
			setTimeout("$wnd.justUp()",timeLimit);
		}
	 
		$wnd.justUp = function ()
		{

			if($wnd.keysUpOut.length > 0)
			{
				key = $wnd.keysUpOut.shift();
				$wnd.keysUp[key] = false;
				 
			}
		}
				
				
		function mouseDown(event)
		{
			 if (event.which == null)
		       id = (event.button < 2) ? "LEFT" :
		                 ((event.button == 4) ? "MIDDLE" : "RIGHT");
		    else
		       id = (event.which < 2) ? "LEFT" :
		                 ((event.which == 2) ? "MIDDLE" : "RIGHT");
			$wnd.buttonD[id] = true;
		}
		 
		function mouseUp(event)
		{
		
			 
			if (event.which == null)
		       id = (event.button < 2) ? "LEFT" :
		                 ((event.button == 4) ? "MIDDLE" : "RIGHT");
		    else
		       id = (event.which < 2) ? "LEFT" :
		                 ((event.which == 2) ? "MIDDLE" : "RIGHT");
			 
			if(id in $wnd.buttonD && $wnd.buttonD[id] )
			{
				$wnd.buttonD[id] = false;
				$wnd.buttonU[id] = true;
				$wnd.mouseOut.push(id);
				setTimeout("$wnd.clickEnd()",timeLimit);
			}
		}
		$wnd.keysChar = function(checkKey, array, oneUse)
		{
			
	 		var retVal = false;
	 		 
			if(checkKey.length == 1)
			{
				
				checkKey = checkKey.toUpperCase();
				var code = checkKey.charCodeAt(0);
				
				if(code in array && array[code])
				{
					//$wnd.alert("apretado");
					retVal  = true;
					 
 
					if(oneUse)
			 			array[code] = false;
				}
			
			}//Casos especiales
			else
			{
						
				var especialKey = null;
		 
				if ((checkKey == 'left' || checkKey == 'LEFT') && (37 in array && array[37]))
				{
				 	retVal  = true;
				 	especialKey = 37;
				}
				else if ((checkKey == 'right' || checkKey == 'RIGHT') && (39 in array && array[39]))
				{
				  	retVal  = true;
				  	especialKey = 39;
				}
				else if ((checkKey == 'up' || checkKey == 'UP') && (38 in array && array[38]))
				{
				  	retVal  = true;
				  	especialKey = 38;
				}
				else if ((checkKey == 'down' || checkKey == 'DOWN') && (40 in array && array[40]))
				{
					retVal  = true;
					especialKey = 40;
				}
				else if ((checkKey == 'esc' || checkKey == 'ESC' || checkKey == 'escape' || checkKey == 'ESCAPE' ) && (27 in array && array[27]))
				{
				  retVal  = true;
				  especialKey = 27;
				}
				
				if(oneUse)
					array[especialKey] = false;
			}

			 return retVal;
		}
		//$wnd.alert('Hecho IO');
	  }-*/;


	
	@Override
	public native boolean keyPressed(String key) throws FunctionNonSuported  
	/*-{
		//$wnd.alert("consulta" +key);
	 	 return $wnd.keysChar(key, $wnd.keys,false);
	 }-*/;
	@Override
	public native boolean keyDown(String key) throws FunctionNonSuported 
	/*-{
 		 return $wnd.keysChar(key,$wnd.keysDown,true);
 		 
	 }-*/;
	@Override
	public native boolean keyUp(String key) throws FunctionNonSuported  
	/*-{
	 	return $wnd.keysChar(key, $wnd.keysUp,true);
	 }-*/;
	@Override
	public native boolean mouseDown(String button) throws FunctionNonSuported 
	/*-{
	 	if(button in $wnd.buttonD && $wnd.buttonD[button] )
	 	{
			return true;
		}
		return false;
	 }-*/;
	@Override
	public native boolean mouseUp(String button) throws FunctionNonSuported  
	/*-{
		if(button in $wnd.buttonU && $wnd.buttonU[button] )
		{
		 	$wnd.buttonU[button] = false;
			return true;
		}
		return false;
	 }-*/;

	@Override
	public native final double mouseX()
	/*-{ 
		
		//$wnd.alert("MoqqqWuse: X="+$wnd.mouseX+",Y="+$wnd.mouseY);
		return Math.min(Math.max($wnd.mouseX-$wnd._canvas[$wnd._layer].offsetLeft,0),$wnd._canvas[$wnd._layer].width);
	}-*/;

	@Override
	public native final double mouseY() 
	/*-{
		return Math.min(Math.max($wnd.mouseY-$wnd._canvas[$wnd._layer].offsetTop,0), $wnd._canvas[$wnd._layer].height);
	}-*/;
}
